// import com.alibaba.druid.DbType;
// import com.alibaba.druid.sql.PagerUtils;
// import com.alibaba.druid.sql.SQLUtils;
// import com.alibaba.druid.sql.ast.*;
// import com.alibaba.druid.sql.ast.expr.*;
// import com.alibaba.druid.sql.ast.statement.*;
// import com.alibaba.druid.sql.visitor.SQLASTVisitor;
// import com.alibaba.druid.wall.spi.WallVisitorUtils;
// import com.alibaba.druid.wall.violation.ErrorCode;
// import com.alibaba.druid.wall.violation.IllegalSQLObjectViolation;

// import java.util.List;
#pragma once
#include "../sql/visitor/SQLASTVisitor.h"

class WallVisitor : virtual public SQLASTVisitor
{
public:
  virtual WallConfig_ptr getConfig() = 0;

  // WallProvider getProvider();

  // List<Violation> getViolations();

  virtual void addViolation(Violation_ptr violation) = 0;

  // bool isDenyTable(std::string name);

  std::string toSQL(SQLObject_ptr obj);

  // bool isSqlModified();

  // void setSqlModified(bool sqlModified);

  virtual DbType_ptr getDbType() = 0;

  // bool isSqlEndOfComment();

  // void setSqlEndOfComment(bool sqlEndOfComment);

  // void addWallUpdateCheckItem(WallUpdateCheckItem item);

  // List<WallUpdateCheckItem> getUpdateCheckItems();

  // bool visit(SQLPropertyExpr x) {
  //     WallVisitorUtils.check(this, x);
  //     return true;
  // }

  // bool visit(SQLInListExpr x) {
  //     WallVisitorUtils.check(this, x);
  //     return true;
  // }

  // bool visit(SQLBinaryOpExpr x) {
  //     return WallVisitorUtils.check(this, x);
  // }

  // bool visit(SQLMethodInvokeExpr x) {
  //     WallVisitorUtils.checkFunction(this, x);
  //     return true;
  // }

  // bool visit(SQLSelectQueryBlock x) {
  //     WallVisitorUtils.checkSelelct(this, x);

  //     return true;
  // }

  // bool visit(SQLSelectGroupByClause x) {
  //     WallVisitorUtils.checkHaving(this, x.getHaving());
  //     return true;
  // }

  // // @Override
  // bool visit(SQLSelectItem x) {
  //     WallVisitorUtils.check(this, x);
  //     return true;
  // }

  // bool visit(SQLJoinTableSource x) {
  //     WallVisitorUtils.check(this, x);
  //     return true;
  // }

  // bool visit(SQLCreateTableStatement x) {
  //     WallVisitorUtils.check(this, x);
  //     return true;
  // }

  // bool visit(SQLAlterTableStatement x) {
  //     WallVisitorUtils.check(this, x);
  //     return true;
  // }

  // bool visit(SQLDropTableStatement x) {
  //     WallVisitorUtils.check(this, x);
  //     return true;
  // }

  // bool visit(SQLUpdateStatement x) {
  //     WallVisitorUtils.initWallTopStatementContext();
  //     WallVisitorUtils.checkUpdate(this, x);

  //     return true;
  // }

  // void endVisit(SQLUpdateStatement x) {
  //     WallVisitorUtils.clearWallTopStatementContext();
  // }

  // bool visit(SQLInsertStatement x) {
  //     WallVisitorUtils.initWallTopStatementContext();
  //     WallVisitorUtils.checkInsert(this, x);

  //     return true;
  // }

  // void endVisit(SQLInsertStatement x) {
  //     WallVisitorUtils.clearWallTopStatementContext();
  // }

  // bool visit(SQLDeleteStatement x) {
  //     WallVisitorUtils.checkDelete(this, x);
  //     return true;
  // }

  // void preVisit(SQLObject_ptr x) {
  //     WallVisitorUtils.preVisitCheck(this, x);
  // }

  // // @Override
  // bool visit(SQLSelectStatement x) {
  //     WallConfig config = getConfig();
  //     if (!config.isSelectAllow()) {
  //         this.getViolations()
  //                 .add(new IllegalSQLObjectViolation(ErrorCode.SELECT_NOT_ALLOW, "select not allow",
  //                         this.toSQL(x)));
  //         return false;
  //     }

  //     WallVisitorUtils.initWallTopStatementContext();

  //     int selectLimit = config.getSelectLimit();
  //     if (selectLimit >= 0) {
  //         SQLSelect select = x.getSelect();
  //         PagerUtils.limit(select, getDbType(), 0, selectLimit, true);
  //         setSqlModified(true);
  //     }
  //     return true;
  // }

  // void endVisit(SQLSelectStatement x) {
  //     WallVisitorUtils.clearWallTopStatementContext();
  // }

  // bool visit(SQLExprTableSource x) {
  //     WallVisitorUtils.check(this, x);

  //     if (x.getExpr() instanceof SQLName) {
  //         return false;
  //     }

  //     return true;
  // }

  // bool visit(SQLIdentifierExpr x) {
  //     WallConfig config = getConfig();
  //     std::string name = x.getName();
  //     name = WallVisitorUtils.form(name);
  //     if (config.isVariantCheck() && config.getDenyVariants().contains(name)) {
  //         getViolations().add(new IllegalSQLObjectViolation(ErrorCode.VARIANT_DENY, "variable not allow : " + name,
  //                 toSQL(x)));
  //     }
  //     return true;
  // }

  // bool visit(SQLUnionQuery x) {
  //     return WallVisitorUtils.checkUnion(this, x);
  // }

  // void endVisit(SQLDeleteStatement x) {
  //     WallVisitorUtils.clearWallTopStatementContext();
  // }

  // bool visit(SQLLimit x) {
  //     if (x.getRowCount() instanceof SQLNumericLiteralExpr) {
  //         WallContext context = WallContext.current();

  //         int rowCount = ((SQLNumericLiteralExpr) x.getRowCount()).getNumber().intValue();
  //         if (rowCount == 0) {
  //             if (context != null) {
  //                 context.incrementWarnings();
  //             }

  //             if (!getProvider().getConfig().isLimitZeroAllow()) {
  //                 this.getViolations().add(new IllegalSQLObjectViolation(ErrorCode.LIMIT_ZERO, "limit row 0",
  //                         this.toSQL(x)));
  //             }
  //         }
  //     }
  //     return true;
  // }

  // bool visit(SQLCreateTriggerStatement x) {
  //     return false;
  // }

  // bool visit(SQLSetStatement x) {
  //     return false;
  // }

  // bool visit(SQLCallStatement x) {
  //     return false;
  // }

  // bool visit(SQLCommentHint x) {
  //     if (x instanceof TDDLHint) {
  //         return false;
  //     }
  //     WallVisitorUtils.check(this, x);
  //     return true;
  // }

  // bool visit(SQLShowCreateTableStatement x) {
  //     std::string tableName = (x.getName()).getSimpleName();
  //     WallContext context = WallContext.current();
  //     if (context != null) {
  //         WallSqlTableStat tableStat = context.getTableStat(tableName);
  //         if (tableStat != null) {
  //             tableStat.incrementShowCount();
  //         }
  //     }
  //     return false;
  // }
};
